/*
XPTracker - Alternative Agile Tracking Tool
Copyright (C) 2006-2009  Stephen Starkey

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/
package org.xptracker.services;

import junit.framework.TestCase;
import org.xptracker.domain.Queue;
import org.xptracker.domain.State;
import org.xptracker.domain.Story;
import org.xptracker.domain.User;

public class StoryStateTest extends TestCase {
  public void testNextActionStates() throws Exception {
    Story s = new Story();
    assertEquals(new State[] {State.inProcess, State.rejected, State.inQueue}, StoryState.getNextActionStates(s));

    s.setState(State.inQueue);
    assertEquals(new State[] {State.inProcess, State.dreaming, State.inQueue}, StoryState.getNextActionStates(s));

    s.setState(State.inProcess);
    assertEquals(new State[] {State.developed, State.blocked, State.dreaming, State.inQueue}, StoryState.getNextActionStates(s));

    s.setState(State.blocked);
    assertEquals(new State[] {State.inProcess, State.inQueue}, StoryState.getNextActionStates(s));

    s.setState(State.developed);
    assertEquals(new State[] {State.inProcess, State.tested, State.inQueue}, StoryState.getNextActionStates(s));

    s.setState(State.tested);
    assertEquals(new State[] {State.released, State.inProcess, State.inQueue}, StoryState.getNextActionStates(s));

    s.setState(State.rejected);
    assertEquals(new State[] {State.dreaming, State.inQueue}, StoryState.getNextActionStates(s));

    s.setState(State.released);
    assertEquals(new State[] {State.inProcess, State.inQueue}, StoryState.getNextActionStates(s));
  }

  public void testRealizationVerbs() throws Exception {
    assertEquals("Accept", StoryState.getRealizationVerb(State.dreaming, State.inProcess));
    assertEquals("Reject", StoryState.getRealizationVerb(State.dreaming, State.rejected));
    assertEquals("Restore", StoryState.getRealizationVerb(State.rejected, State.dreaming));
    assertEquals("Reopen", StoryState.getRealizationVerb(State.developed, State.inProcess));
    assertEquals("Complete", StoryState.getRealizationVerb(State.inProcess, State.developed));
    assertEquals("Block", StoryState.getRealizationVerb(State.inProcess, State.blocked));
    assertEquals("Unblock", StoryState.getRealizationVerb(State.blocked, State.inProcess));
    assertEquals("Verify", StoryState.getRealizationVerb(State.developed, State.tested));
    assertEquals("Release", StoryState.getRealizationVerb(State.tested, State.released));
    assertEquals("Dreaming", StoryState.getRealizationVerb(State.inProcess, State.dreaming));
    assertEquals("Re-Enqueue", StoryState.getRealizationVerb(State.inProcess, State.inQueue));
    assertEquals("Reopen", StoryState.getRealizationVerb(State.tested, State.inProcess));
    assertEquals("Reopen", StoryState.getRealizationVerb(State.released, State.inProcess));
    assertEquals("Re-Enqueue", StoryState.getRealizationVerb(State.inProcess, State.inQueue));
  }

  public void testSetNextState() throws Exception {
    Story s = new Story();
    TestVisitor v = new TestVisitor();
    StoryState.setNextState(v, s, State.inProcess, false);
    assertTrue(v.currentUserSet);
    assertFalse(v.addTracker);
    assertFalse(v.removeFromQueue);
    assertFalse(v.removeOwner);

    v = new TestVisitor();
    s.setState(State.dreaming);
    StoryState.setNextState(v, s, State.rejected, false);
    assertFalse(v.currentUserSet);
    assertTrue(v.addTracker);
    assertTrue(v.removeFromQueue);
    assertTrue(v.removeOwner);

    v = new TestVisitor();
    s.setState(State.inProcess);
    StoryState.setNextState(v, s, State.developed, false);
    assertFalse(v.currentUserSet);
    assertFalse(v.addTracker);
    assertFalse(v.removeFromQueue);
    assertFalse(v.removeOwner);

    User owner = new User("george");
    v = new TestVisitor();
    Queue q = new Queue("bob");
    s.setState(State.inProcess);
    s.setQueue(q);
    s.changeOwner(owner);
    assertTrue(q.getStories().isEmpty());
    StoryState.setNextState(v, s, State.inQueue, false);
    assertFalse(v.currentUserSet);
    assertFalse(v.addTracker);
    assertFalse(v.removeFromQueue);
    assertTrue(v.removeOwner);

    q.remove(s);
    v = new TestVisitor();
    s.setState(State.inProcess);
    s.changeOwner(owner);
    s.setQueue(null);
    StoryState.setNextState(v, s, State.inQueue, false);
    assertFalse(v.currentUserSet);
    assertFalse(v.addTracker);
    assertFalse(v.removeFromQueue);
    assertTrue(v.removeOwner);
    assertTrue(q.getStories().isEmpty());

    v = new TestVisitor();
    s.setState(State.inProcess);
    s.changeOwner(owner);
    StoryState.setNextState(v, s, State.dreaming, false);
    assertFalse(v.currentUserSet);
    assertFalse(v.addTracker);
    assertFalse(v.removeFromQueue);
    assertTrue(v.removeOwner);

    v = new TestVisitor();
    s.setState(State.inQueue);
    StoryState.setNextState(v, s, State.inProcess, false);
    assertTrue(v.currentUserSet);
    assertFalse(v.addTracker);
    assertTrue(v.removeFromQueue);
    assertFalse(v.removeOwner);

  }

  private class TestVisitor implements StoryState.StoryStateVisitor {
    private boolean currentUserSet;
    private boolean addTracker;
    private boolean removeFromQueue;
    private boolean removeOwner;

    public void setCurrentUser() {
      currentUserSet = true;
    }

    public void addCurrentUserAsTracker() {
      addTracker = true;
    }

    public void removeFromQueue(String reason) {
      removeFromQueue = true;
    }

    public void removeOwner() {
      removeOwner = true;
    }
  }

  public void assertEquals(Object[] expected, Object[] actual) {
    if (expected != null && actual != null) {
      if (expected.length == actual.length) {
        for (int i = 0; i < expected.length; i++) {
          assertEquals(expected[i], actual[i]);
        }
      } else {
        fail("Arrays are not the same length");
      }
    } else {
      fail("Can not assert against null arrays.");
    }
  }
}
